"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const crypto = require("crypto");
function toBase64Url(str) {
  return str.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
}
function fromBase64Url(base64url) {
  base64url = base64url.toString();
  var padding = 4 - base64url.length % 4;
  if (padding !== 4) {
    for (var i = 0; i < padding; ++i) {
      base64url += "=";
    }
  }
  return base64url.replace(/-/g, "+").replace(/_/g, "/");
}
function atob(str) {
  return Buffer.from(str, "base64").toString("utf-8");
}
function btoa(str) {
  return Buffer.from(str, "utf-8").toString("base64");
}
function fromToken(base64url) {
  return JSON.parse(atob(fromBase64Url(base64url)));
}
function toToken(obj) {
  return toBase64Url(btoa(JSON.stringify(obj)));
}
function getSign(str, secret) {
  return toBase64Url(crypto.createHmac("sha256", secret).update(str).digest("base64"));
}
const jwt = {
  verify: function(token, secret) {
    if (typeof token !== "string") {
      throw new Error("Invalid token");
    }
    const tokenArr = token.split(".");
    if (tokenArr.length !== 3) {
      throw new Error("Invalid token");
    }
    const [headerBase64, payloadBase64, signatureBase64] = tokenArr;
    if (getSign(headerBase64 + "." + payloadBase64, secret) !== signatureBase64) {
      throw new Error("Invalid token");
    }
    const header = fromToken(headerBase64);
    if (header.alg !== "HS256" || header.typ !== "JWT") {
      throw new Error("Invalid token");
    }
    const payload = fromToken(payloadBase64);
    if (payload.exp * 1e3 < Date.now()) {
      const err = new Error("Token expired");
      err.name = "TokenExpiredError";
      throw err;
    }
    return payload;
  },
  sign: function(data, secret, expiresIn) {
    if (!expiresIn) {
      throw new Error("expiresIn is required");
    }
    const header = {
      alg: "HS256",
      typ: "JWT"
    };
    const now = parseInt(`${Date.now() / 1e3}`);
    const payload = {
      ...data,
      iat: now,
      // 过期的也是秒
      exp: now + expiresIn
    };
    const signStr = toToken(header) + "." + toToken(payload);
    const signature = getSign(signStr, secret);
    return signStr + "." + signature;
  }
};
exports.jwt = jwt;
